package com.dream.fly.juststartpractice.config;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.stream.Collectors;

/**
 * @author: 熊海梦
 * @date: 2018/11/9 19:55
 **/
@Aspect
@Component
@Slf4j
public class WebLogAspect {

    /**
     * 定义一个切入点，可以是一个规则表达式，比如下例中某个package下的所有函数，也可以是一个注解等
     */
    @Pointcut(value = "execution(public * com.dream.fly.juststartpractice.*.*(..))")
    public void weblog() {
    }

    @Around("weblog()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        String requestUrl = attributes.getRequest().getMethod() + attributes.getRequest().getServletPath();
        log.info("请求源IP：{}，URL：{}，START：{}", attributes.getRequest().getRemoteAddr(), requestUrl,
                parseParamArr(proceedingJoinPoint.getArgs()));
        Object re = proceedingJoinPoint.proceed();
        log.info("请求源IP：{}，URL：{}，END：{}", attributes.getRequest().getRemoteAddr(),
                requestUrl, parseParam(re));
        return re;
    }

    private String parseParam(Object param) {
        if (param instanceof ModelAndView) {
            return "";
        }
        return JSON.toJSONString(param);
    }

    private String parseParamArr(Object[] paramArr) {
        if (paramArr.length == 0) {
            return "";
        }
        return JSON.toJSONString(Arrays.asList(paramArr).stream()
                .filter(s -> !(s instanceof HttpServletRequest) && !(s instanceof BindingResult))
                .collect(Collectors.toList()));
    }

}
